#!/usr/bin/env bash

# 当前脚本所在目录
ROOT_DIR="$(pwd)"

# 节点日志存储目录
LOG_FILE="/var/log/redis/cluster"

# 默认节点数
NODES=6

# 默认起始端口号
PORT=30001

# 默认主节点的从节点数
REPLICAS=1

# 操作选项数组
declare -a OPIONS

# 定义帮助信息
help_str="
参数说明:
    -c,--create [           创建集群指令
        -n <node number>    指定集群节点数量
        -s <slave number>   指定集群每个主节点的从节点数量
        -p <port>           指定集群节点起始端口号
        ]              
    --start:                启动集群所有节点指令
    --stop:                 停止集群所有节点命令
    --restart:              重启集群所有节点指令
    --clean:                清除集群所有节点指令
    -l,--list:              打印集群中当前正在运行的节点进程信息
    -h,--help:              打印帮助信息
"

function echo_help() {
    echo -e "\033[1;34m$help_str\033[0m"
}

function echo_ok () {
    echo -e "\033[1;32m$1\033[0m"
}


# 解析命令行选项
getopt_cmd=$(getopt -o clhn:s:p: --long create,start,stop,restart,clean,list,help -n "$(basename "$0")" -- "$@")

# 判断命令是否异常终结
[ $? != 0 ] && exit 1

# 使用eval命令防止getopt命令参数中含有shell脚本命令
eval set -- "$getopt_cmd"

# 开始解析命令行选项及参数
while [ -n "$1" ]; do
    case "$1" in
        -n) NODES="$2"
        shift
        ;;
        -s) REPLICAS="$2"
        shift
        ;;
        -p) PORT="$2"
        shift
        ;;
        -c | --create)
        OPIONS=("${OPIONS[@]}" "$1")
        ;;
        --start)
        OPIONS=("${OPIONS[@]}" "$1")
        ;;
        --stop)
        OPIONS=("${OPIONS[@]}" "$1")
        ;;
        --restart)
        OPIONS=("${OPIONS[@]}" "$1")
        ;;
        --clean)
        OPIONS=("${OPIONS[@]}" "$1")
        ;;
        -l | --list)
        OPIONS=("${OPIONS[@]}" "$1")
        ;;
        -h | --help)
        echo_help
        ;;
        --) shift
        break 
        ;;
        *) echo default
        ;;
    esac
    shift
done

# 启动节点
function start() {
    # 从cluster.conf中获取当前集群节点总数
    num=$(sed '/^node-num=/!d;s/.*=//' ./cluster.conf)

    echo "Start all nodes in the cluster..."

    for((i=1;i<="$num";i++)); do
        node_dir="$ROOT_DIR/nodes/node$i"
        cd "$node_dir" || exit
        ./redis-server ./conf/redis.conf --daemonize yes
        echo "Node $i is started successfully!"
    done
    # 退回到根目录下
    cd "$ROOT_DIR" || exit
    echo_ok  "[OK] All $num nodes are started successfully!"
}

# 创建节点
function create() {
    echo_ok "Creating all nodes in the cluster..."
    
    p=$PORT  # 当前节点端口号
    
    address=""  # 记录各节点的访问地址,如 127.0.0.1:30001

    # 将nodes、port、replicas选项值写入配置文件
    sed -i -r "s/^node-num=.*/node-num=$NODES/" ./cluster.conf
    sed -i -r "s/^start-port=.*/start-port=$PORT/" ./cluster.conf
    sed -i -r "s/^node-replicas=.*/node-replicas=$REPLICAS/" ./cluster.conf

    for((i=1;i<="$NODES";i++)); do
        echo "Createing the node $i which port is $p"
        node_dir="${ROOT_DIR}/nodes/node$i"
        mkdir -p "$node_dir"
        mkdir -p "$node_dir/conf"
        mkdir -p "$node_dir/data"

        # 复制redis-server
        cp ./temp/redis-server "$node_dir"
        # 复制redis.conf
        cp ./temp/redis.conf  "$node_dir/conf"
        # 修改节点配置文件的端口号及日志文件配置
        sed -i -r "s/\{port\}/$p/" "$node_dir/conf/redis.conf"
        sed -i -r "s/\{logfile\}/\/var\/log\/redis\/cluster\/redis_$p.log/" "$node_dir/conf/redis.conf"

        # 创建集群日志目录
        mkdir -p "$LOG_FILE"
        # 创建当前节点的日志文件
        touch "$LOG_FILE/redis_$p.log"
        # 授权日志文件访问权限
        chmod -R 777 "$LOG_FILE/redis_$p.log"
        address=$address"127.0.0.1:$p "
        ((p++))
    done
    # 将各节点访问地址写入cluster.conf配置文件
    sed -i -r "s/^node-address=.*/node-address=$address/" ./cluster.conf
    
    echo_ok "[OK] All $NODES nodes are created successfully!"

    # 启动各个节点服务器
    start

    # 配置集群节点
    echo "Config the cluster......"
    # 读取配置文件中各个节点的访问地址node-address及replicas
    nodesAddress=$(sed '/^node-address=/!d;s/.*=//' ./cluster.conf)
    replicas=$(sed '/^node-replicas=/!d;s/.*=//' ./cluster.conf)

    ./temp/redis-cli --cluster create $nodesAddress --cluster-replicas $replicas
}

# 解析选项

for option in "${OPIONS[@]}"; do
    if [ "$option" = "" ]; then
         exit 1
    elif [ "$option" = "-c" ] || [ "$option" = "--create" ]; then
         create
    elif [ "$option" = "--start" ]; then
         start
    elif [ "$option" = "--stop" ]; then
         echo "Stop all nodes in the cluster"
         pkill -f -e "redis-server"
         echo_ok "[OK] All nodes are killed..."
    elif [ "$option" = "--restart" ]; then
         echo "Stop all nodes in the cluster"
         pkill -f -e "redis-server"
         start
    elif [ "$option" = "--clean" ]; then
         # 关闭各个节点redis-server服务进程
         pkill -f -e "redis-server"
         # 删除日志文件
         rm -f $LOG_FILE"/*.log"
         # 清除节点
         rm -f -r ./nodes
         echo_ok "[OK] All nodes are deleted..."
    elif [ "$option" = "-l" ] || [ "$option" = "--list" ]; then
         echo "All nodes process information as follows"
         pgrep -f -a "redis-server"
    else
         exit 1
    fi
    
done

